#include "Primitive.h"
#include "Graphics.h"

Graphics* g;

Primitive::Primitive(Config* config, string Name, string Type, Graphics* graphics) {
	this->config = config;
	this->ID     = config->GetNewID();
	this->Name   = Name;
	this->Type   = Type;
    g = graphics;
    textureFaces = new vector<Shape::TextureFace*>;
}

Primitive* Primitive::GetCopy() {
	Primitive* copy    = new Primitive(config, Name, Type, g);
	copy->FaceLength   = FaceLength;
	copy->Translation  = Translation;
	copy->Scaling      = Scaling;
	copy->Rotation     = Rotation;
	for(UINT i=0; i<textureFaces->size(); i++)
		copy->textureFaces->push_back(textureFaces->at(i));
	return copy;
}

int Primitive::GetNrOfVertices() {
    return (int)textureFaces->size() * 6;
}

XMVECTOR Primitive::GetLowest() {
	XMVECTOR result = XMVectorSet(*(float*)std::numeric_limits<float>::max,
		                          *(float*)std::numeric_limits<float>::max,
								  *(float*)std::numeric_limits<float>::max,
								  0.0f);
	for(UINT i=0; i<textureFaces->size(); i++) {
        for(int j=0; j<6; j++) { //every texture face has 6 indices
            //Retrieve position of vertex for each index in vertex array in graphics
            DWORD vertexNumber = textureFaces->at(i)->indices[j];
            //Retrieve corresponding vertex
            Primitive::VERTEX v = g->allVertices->at((int)vertexNumber);
            //update result
			float x = (v.X < XMVectorGetX(result)) ? v.X : XMVectorGetX(result); XMVectorSetX(result, x);
			float y = (v.Y < XMVectorGetY(result)) ? v.Y : XMVectorGetY(result); XMVectorSetY(result, y);
			float z = (v.Z < XMVectorGetZ(result)) ? v.Z : XMVectorGetZ(result); XMVectorSetZ(result, z);
        }
	}
	return result;
}

XMVECTOR Primitive::GetHighest() {
	XMVECTOR result = XMVectorSet(*(float*)std::numeric_limits<float>::min,
		                          *(float*)std::numeric_limits<float>::min,
								  *(float*)std::numeric_limits<float>::min,
								  0.0f);
    for(UINT i=0; i<textureFaces->size(); i++) {
        for(int j=0; j<6; j++) { //every texture face has 6 indices
            //Retrieve position of vertex for each index in vertex array in graphics
            DWORD vertexNumber = textureFaces->at(i)->indices[j];
            //Retrieve corresponding vertex
            Primitive::VERTEX v = g->allVertices->at((int)vertexNumber);
            //update result
			float x = (v.X > XMVectorGetX(result)) ? v.X : XMVectorGetX(result); XMVectorSetX(result, x);
			float y = (v.Y > XMVectorGetY(result)) ? v.Y : XMVectorGetY(result); XMVectorSetY(result, y);
			float z = (v.Z > XMVectorGetZ(result)) ? v.Z : XMVectorGetZ(result); XMVectorSetZ(result, z);
        }
	}
	return result;
}

XMVECTOR Primitive::GetCenter() {
	XMVECTOR sum = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
    
    for(UINT i=0; i<textureFaces->size(); i++) {
        for(int j=0; j<6; j++) { //every texture face has 6 indices
            //Retrieve position of vertex for each index in vertex array in graphics
            DWORD vertexNumber = textureFaces->at(i)->indices[j];
            //Retrieve corresponding vertex
            Primitive::VERTEX v = g->allVertices->at((int)vertexNumber);
            //update sum
			XMVectorSetX(sum, XMVectorGetX(sum) + v.X);
			XMVectorSetY(sum, XMVectorGetY(sum) + v.Y);
			XMVectorSetZ(sum, XMVectorGetZ(sum) + v.Z);
        }
	}
    return sum/(float)GetNrOfVertices();
}

void Primitive::Translate(XMVECTOR transl) {
    for(UINT i=0; i<textureFaces->size(); i++)
        textureFaces->at(i)->translation = XMVectorSet(XMVectorGetX(transl) + XMVectorGetX(Translation),
                                                       XMVectorGetY(transl) + XMVectorGetY(Translation),
                                                       XMVectorGetZ(transl) + XMVectorGetZ(Translation),
													   0.0f);
}

void Primitive::Scale(XMVECTOR scal) {
    for(UINT i=0; i<textureFaces->size(); i++)
        textureFaces->at(i)->scaling = XMVectorSet(XMVectorGetX(scal) * XMVectorGetX(Scaling),
                                                   XMVectorGetY(scal) * XMVectorGetY(Scaling),
                                                   XMVectorGetZ(scal) * XMVectorGetZ(Scaling),
												   0.0f);
}

void Primitive::Rotate(XMVECTOR rotat) {
    for(UINT i=0; i<textureFaces->size(); i++)
        textureFaces->at(i)->rotation = XMVectorSet(XMVectorGetX(rotat) + XMVectorGetX(Rotation),
                                                    XMVectorGetY(rotat) + XMVectorGetY(Rotation),
                                                    XMVectorGetZ(rotat) + XMVectorGetZ(Rotation),
													0.0f);
}